#ifndef FILETRANSFERWINDOW_H
#define FILETRANSFERWINDOW_H

#include "filetransferhelper.h"
#include "modelserver.h"
#include "wsockclienthelper.h"

#include <QMainWindow>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QMessageBox>
#include <QDir>
#include <QStandardItemModel>
#include <QIcon>
#include <QFileIconProvider>
#include <QMutex>

namespace Ui {
class FileTransferWindow;

}

/*
 * 文件传输内容
 * */
class FileTransferInfo
{
public:
    enum TransferStatus{
        waitToTransfer,                 //等待传输
        transfering,                    //传输中
        complete,                       //传输完成
        error                           //传输错误
    };

    FileTransferInfo();
    /*  对于下载文件：
     *  sfullPath为客户端这边能看到的服务器文件名全称，如：/abc/opq/xyz/mi.cfg；
     *  sbasePath为服务端当前打开的目录，如：/abc/opq；
     *  dbasePath为本地当前打开的目录，是用于存放下载文件的文件夹，如：e:/download；
     *  对于上传文件：
     *  sfullPath为本地文件全名，如：e:/abc/opq/xyz/mi.cfg;
     *  sbasePath为本地的相对路径，如：当前路径为 e:/abc/，用于右击opq文件夹点击上传，该参数就是/opq/xyz/mi.cfg;
     *  dbasePath为服务器当前打开的目录，用于存放上传文件的文件夹，如：/abc/mmm；
     *  不管上传还是下载，所有目录前后的斜杠都不做要求，既可以有也可以没有，由服务端来处理
     * */
    FileTransferInfo(QString fileId, QString sfullPath, QString sbasePath, QString dbasePath,
                     qint64 flength, bool exists, bool isdownload);
    ~FileTransferInfo();
    bool isEmpty();

public:
    QString transferToken;
    QString fileGuid;
    QString sourceFullPath;                 //如：/abc/opq/xyz/mi.cfg
    QString sourceBasePath;                 //如：/abc/opq
    QString destBasePath;                   //如：e:/download
    qint64 fileLength;
    bool isExists;
    bool isDownload;
    TransferStatus status = TransferStatus::waitToTransfer;
    QStandardItem* itemProgress;            //进度item，记录之后修改进度时就不用每次都遍历查找了
};

/*
 * 文件传输窗口
 * */
class FileTransferWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit FileTransferWindow(QWidget *parent = nullptr);
    ~FileTransferWindow();
    void connectToServer(ModelServer info);
    static QString convertFileSize(qint64 length);                              //转换文件大小

private:
    Ui::FileTransferWindow *ui;
    const int m_fcons = 5;                                                      //文件传输最大连接数
    int m_sw1 = 360;                                                            //服务端tableview第一列默认宽度
    int m_sw2 = 100;                                                            //服务端tableview第二列默认宽度
    int m_sw3 = 100;                                                            //服务端tableview第三列默认宽度
    int m_lw1 = 360;                                                            //本地端tableview第一列默认宽度
    int m_lw2 = 100;                                                            //本地端tableview第一列默认宽度
    int m_lw3 = 100;                                                            //本地端tableview第一列默认宽度
    bool m_lvtransferInited = false;                                            //文件传输表格是否已经初始化
    bool m_lvcompleteInited = false;                                            //文件传输完成表格是否已经初始化
    QString m_url;
    QString m_furl;                                                             //服务器的文件传输专用连接地址
    QString m_userName;
    QString m_passWd;
    QString m_currentSevPath;
    QString m_currentLocalPath;
    WSockClientHelper* m_whelper;
    bool m_isInit = false;
    QIcon m_folder;// = QIcon(":/icon/icon/folder.png");                        //文件夹图标，放弃自定义图标，改为系统图标
    QIcon m_file;// = QIcon(":/icon/icon/file.png");                            //文件图标，放弃自定义图标，改为系统图标
    QStandardItemModel* m_modelServer = new QStandardItemModel(this);           //服务器目录模型
    QStandardItemModel* m_modelLocal = new QStandardItemModel(this);            //本地目录模型
    QStandardItemModel* m_modelTransfer = new QStandardItemModel(this);         //文件传输模型
    QStandardItemModel* m_modelComplete = new QStandardItemModel(this);         //文件传输完成模型
    QMenu* m_serverMenus;                                                       //服务端右键菜单
    QMenu* m_localMenus;                                                        //本地右键菜单
    QList<FiletransferHelper*> m_transferConns;                                 //用于上传和下载的连接
    QMutex* m_lvtranMutex = new QMutex();                                       //界面下方传输列表的锁
    QMutex* m_tranHelperMutex = new QMutex();                                   //传输helper列表的锁
    QList<FileTransferInfo> m_waitToUploads;                                    //待上传的文件列表，在用于右键文件夹点击上传后赋值，然后向服务器发送上传请求，在服务器回应请求成功后，
                                                                                //客户端通过该变量内容向m_modelTransfer中添加行，添加完成后该变量的内容失效

private:
    QString convertMapToJsonString(QMap<QString,QString> map);                  //将map转换为json字符串
    void enableUI(bool enable);                                                 //启用/禁用界面所有控件
    void regServerViewColumnSize();                                             //记录服务端列宽
    void dirLocal(QString parent);                                              //列出本地目录
    void transferFile(FiletransferHelper* helper, FileTransferInfo info);       //传输文件
    FileTransferInfo getNextTransferFile();                                     //获取下一个要上传或下载的文件
    FiletransferHelper* createTransferHelper(QString transferToken);            //创建一个传输连接
    void initTransferView();                                                    //初始化传输列表
    void addToTransferView(FileTransferInfo info);                              //添加到传输列表
    void addToCompleteView(QList<QStandardItem*> item, bool isSuccess);         //添加到已完成列表

    void callbackLogin(WSockResponse response);                                 //登录回调
    void callbackListDir(WSockResponse response);                               //列出文件夹/文件回调
    void callbackDownloadFiles(WSockResponse response);                         //请求下载文件列表回调
    void callbackUploadFiles(WSockResponse response);                           //请求上传文件列表回调

private slots:
    void slotConnectServer();
    void slotDisconnected();
    void slotError();
    void slotOnReceiveMessage(WSockResponse response);                          //收到服务器消息回调
    void slotShowServerContextMenu(QPoint p);                                   //显示服务端右键菜单
    void slotShowLocalContextMenu(QPoint p);                                    //显示本地端右键菜单
    void slotTranProgress(FiletransferHelper* helper, int progress);            //文件传输进度
    void slotTranComplete(FiletransferHelper* helper, bool isSuccess);          //文件传输完成
    void on_lvServer_doubleClicked(const QModelIndex &index);
    void on_btnSevUp_clicked();
    void on_lvLocal_doubleClicked(const QModelIndex &index);
    void on_btnLocalUp_clicked();                                               //本地目录上一级
    void on_actionSDownload_triggered();                                        //点击下载菜单
    void on_actionLUpload_triggered();
    void on_btnSevRefresh_clicked();                                            //刷新服务器目录
    void on_btnLocalRefresh_clicked();                                          //刷新本地目录
};

#endif // FILETRANSFERWINDOW_H
